package com.dingwen.treasure.core.aspect;

import cn.hutool.core.lang.Pair;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.dingwen.treasure.base.pojo.vo.Result;
import com.dingwen.treasure.core.annotation.Dic;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StopWatch;

import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 　DicAspect: 字典翻译切面
 * 　@author dingwen
 * 　@date 2022/7/10
 */

@Slf4j
@RequiredArgsConstructor
public abstract class AbstractDicAspect {

    /**
     * 字典切入点表达式
     */
    public abstract void dicPointCut();


    /**
     * 围绕增强进行字段翻译
     *
     * @param proceedingJoinPoint 继续连接点
     * @return {@link Object}
     */
    @SneakyThrows(Throwable.class)
    public Object around(ProceedingJoinPoint proceedingJoinPoint) {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        Object result = proceedingJoinPoint.proceed();
        result = translate(result);
        stopWatch.stop();
        log.info("AOP 字典翻译，耗时：{}毫秒", stopWatch.getTotalTimeMillis());
        return result;
    }


    /**
     * 翻译
     *
     * @param object 返回结果
     * @return {@link Object}
     */
    private Object translate(Object object) {
        // 返回结果为空或不是指定返回类型不进行翻译
        if (ObjectUtils.isEmpty(object) || !(object instanceof Result)) {
            return object;
        }
        Result result = (Result) object;

        // 数据为空不进行字典翻译
        if (ObjectUtils.isEmpty(result.getData())) {
            return result;
        }

        // mongo db 分页
        // mybatis plus 分页
        // 列表
        // 单条记录
        return executeTranslate(result);
    }

    /**
     * 执行翻译
     *
     * @param result 后果
     * @return {@link Object}
     */
    protected abstract Object executeTranslate(Result result);


    /**
     * 转换 list
     *
     * @param list 列表
     * @return {@link List}<{@link JSONObject}>
     */
    @SuppressWarnings("ALL")
    protected List<JSONObject> parseList(List list) {
        return (List<JSONObject>) list.parallelStream()
                .map((ele) -> parse(ele))
                .collect(Collectors.toList());
    }

    /**
     * 转换 单个
     *
     * @param object 对象
     * @return {@link JSONObject}
     */
    protected JSONObject parse(Object object) {
        JSONObject jsonObject = JSONUtil.parseObj(object);
        // 获取需要进行翻译的字段进行翻译
        Arrays.stream(ReflectUtil.getFields(object.getClass()))
                .filter(ele -> !ObjectUtils.isEmpty(ele.getAnnotation(Dic.class)))
                // TODO peek foreach
                .forEach(ele -> {
                    Dic dic = ele.getAnnotation(Dic.class);
                    String code = dic.dicCode();
                    String dicDefaultValue = dic.dicDefaultValue();
                    String name = ele.getName();
                    Pair<String, String> pair = executeParse(code, name);
                    // 若翻译为空则显示默认值
                    String value = Optional.ofNullable(pair.getValue()).orElse(dicDefaultValue);
                    jsonObject.putOpt(pair.getKey(), value);
                });
        return jsonObject;
    }

    /**
     * 执行转换
     *
     * @param code 密码
     * @param name 名称
     * @return {@link Pair}
     */
    protected abstract Pair<String, String> executeParse(String code, String name);

}
